﻿using EpubFactory.Common;
using EpubFactory.Template.V201;
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EpubFactory.Template
{
    public class Epub201Creator : TemplateCreator
    {
        public override void Generate(Book book, string targetFile)
        {
            var target = targetFile + ".epub";
            DeleteFile(target);
            GenerateBookChaptersId(book);
            using (ZipArchive archive = CreateFromTemplate(target))
            {
                ZipArchiveEntry opfEntry = archive.CreateEntry("content.opf", CompressionLevel.Fastest);
                using (StreamWriter writer = new StreamWriter(opfEntry.Open()))
                {
                    var opf = new ContentOPFTemplate(book);
                    writer.Write(opf.TransformText());
                }
                ZipArchiveEntry tocEntry = archive.CreateEntry("toc.ncx", CompressionLevel.Fastest);

                using (StreamWriter writer = new StreamWriter(tocEntry.Open()))
                {
                    var toc = new TocNcxTemplate(book);
                    writer.Write(toc.TransformText());
                }
                if (!string.IsNullOrWhiteSpace(book.CoverUrl) && File.Exists(book.CoverUrl))
                {
                    archive.CreateEntryFromFile(book.CoverUrl, "images/cover.jpg", CompressionLevel.Fastest);
                }
                else
                {
                    var coverEntry = archive.CreateEntry("images/cover.jpg", CompressionLevel.Fastest);
                    using (var stream = coverEntry.Open())
                    {
                        var image = ImageUtil.Generate(book.Title, book.Authors.First());
                        image.Save(stream, ImageFormat.Jpeg);
                    }
                }
                if (book.Images != null)
                {
                    foreach (var img in book.Images)
                    {
                        archive.CreateEntryFromFile(img, "images/" + Path.GetFileName(img), CompressionLevel.Fastest);
                    }
                }
                foreach (var chapter in book.Chapters)
                {
                    ZipArchiveEntry chapterEntry = archive.CreateEntry(chapter.Id + ".html", CompressionLevel.Fastest);
                    using (StreamWriter writer = new StreamWriter(chapterEntry.Open()))
                    {
                        var chapterTemplate = new ChapterHtmlTemplate(chapter);
                        writer.Write(chapterTemplate.TransformText());
                    }
                    if (chapter.Children != null)
                    {
                        foreach (var child in chapter.Children)
                        {
                            ZipArchiveEntry childEntry = archive.CreateEntry(child.Id + ".html", CompressionLevel.Fastest);
                            using (StreamWriter writer = new StreamWriter(childEntry.Open()))
                            {
                                var childTemplate = new ChapterHtmlTemplate(child);
                                writer.Write(childTemplate.TransformText());
                            }
                        }
                    }
                }
            }
        }
        ZipArchive CreateFromTemplate(string targetPath)
        {
            ZipArchive archive = ZipFile.Open(targetPath, ZipArchiveMode.Create);
            var first = archive.CreateEntry("mimetype", CompressionLevel.NoCompression);
            using (StreamWriter writer = new StreamWriter(first.Open()))
            {
                writer.Write("application/epub+zip");
            }
            if (File.Exists(TemplateFile))
            {
                using (ZipArchive zip = ZipFile.Open(TemplateFile, ZipArchiveMode.Read))
                {
                    foreach (ZipArchiveEntry item in zip.Entries)
                    {
                        if (item.Name.Equals("mimetype"))
                        {
                            continue;
                        }
                        var entry = archive.CreateEntry(item.FullName, CompressionLevel.Fastest);
                        using (StreamWriter writer = new StreamWriter(entry.Open()))
                        {
                            using (StreamReader reader = new StreamReader(item.Open()))
                            {
                                writer.Write(reader.ReadToEnd());
                            }
                        }
                    }
                }
            }

            return archive;
        }
    }

}
